package com.fatcat.easybuy.controller;

import com.fatcat.easybuy.annotaion.CheckPermission;
import com.fatcat.easybuy.exception.BusinessException;
import com.fatcat.easybuy.pojo.EasyBuyProduct;
import com.fatcat.easybuy.service.EasyBuyProductService;
import com.fatcat.easybuy.util.ResponseResult;
import com.fatcat.easybuy.util.SftpUtil;
import com.github.pagehelper.PageInfo;
import com.jcraft.jsch.SftpException;
import io.swagger.annotations.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 商品模块控制器
 * 处理商品CRUD、收藏管理、图片上传等业务接口
 */
@Api(tags = "商品模块")
@RestController
@RequestMapping("/product")
public class EasyBuyProductController {

    @Autowired
    private EasyBuyProductService easyBuyProductService;

    @Autowired
    private SftpUtil sftpUtil;

    private static final Logger LOGGER = LoggerFactory.getLogger(EasyBuyProductController.class);

    /**
     * 管理层查询商品（支持分页、多条件筛选）
     * 可按商品名称、三级分类、时间范围筛选，页码和页大小为必填
     */
    @ApiOperation(value = "管理层查询所有商品", notes = "支持分页+多条件筛选；仅传开始时间时，结束时间默认取当前日期；需管理员/普通用户权限", httpMethod = "GET")
    @ApiImplicitParams({@ApiImplicitParam(name = "pageNum", value = "当前页码", required = true, paramType = "query", dataType = "int", example = "1"), @ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, paramType = "query", dataType = "int", example = "10"), @ApiImplicitParam(name = "productName", value = "商品名称（模糊匹配）", required = false, paramType = "query", dataType = "string", example = "手机"), @ApiImplicitParam(name = "categoryLevel1Id", value = "一级分类ID", required = false, paramType = "query", dataType = "int", example = "1"), @ApiImplicitParam(name = "categoryLevel2Id", value = "二级分类ID", required = false, paramType = "query", dataType = "int", example = "2"), @ApiImplicitParam(name = "categoryLevel3Id", value = "三级分类ID", required = false, paramType = "query", dataType = "int", example = "3"), @ApiImplicitParam(name = "startTime", value = "开始时间（yyyy-MM-dd）", required = false, paramType = "query", dataType = "string", example = "2024-01-01"), @ApiImplicitParam(name = "endTime", value = "结束时间（yyyy-MM-dd）", required = false, paramType = "query", dataType = "string", example = "2024-12-31")})
    @ApiResponses({@ApiResponse(code = 200, message = "查询成功", response = PageInfo.class), @ApiResponse(code = 401, message = "参数错误（缺少页码/页大小或时间参数不完整）"), @ApiResponse(code = 500, message = "服务器内部错误")})
    @GetMapping("/getAllProduct")
    public ResponseResult getAllProduct(@RequestParam Map<String, Object> params) {
        LOGGER.info("进入 getAllProduct 方法，接收参数：{}", params);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        // 参数校验：页码和页大小必传
        if (params.get("pageNum") == null || params.get("pageSize") == null) {
            LOGGER.error("getAllProduct 参数错误：缺少页码或页大小");
            return ResponseResult.error("401", "参数错误：页码和页大小为必填项");
        }
        // 时间参数补全：仅传开始时间时，结束时间默认当前日期
        if (params.get("endTime") != null && params.get("startTime") == null) {
            LOGGER.error("getAllProduct 参数错误：仅传结束时间，未传开始时间");
            return ResponseResult.error("401", "参数错误：结束时间需与开始时间同时传入");
        }
        if (params.get("endTime") == null && params.get("startTime") != null) {
            String currentDate = sdf.format(new Date());
            params.put("endTime", currentDate);
            LOGGER.info("getAllProduct 补全结束时间为：{}", currentDate);
        }

        // 查询商品并返回分页结果
        PageInfo<EasyBuyProduct> pageInfo = easyBuyProductService.getAllProduct(params);
        LOGGER.info("getAllProduct 查询完成，总记录数：{}", pageInfo.getTotal());
        return ResponseResult.success().add("pageInfo", pageInfo);
    }

    /**
     * 添加商品（支持图片上传）
     * 仅超级管理员可操作，图片支持jpg/png/jpeg，大小不超过10MB
     */
    @ApiOperation(value = "添加商品", notes = "仅超级管理员权限；图片自动重命名并上传至SFTP；商品信息存入数据库", httpMethod = "POST")
    @ApiImplicitParams({@ApiImplicitParam(name = "easyBuyProduct", value = "商品信息（含名称、价格等）", required = true, paramType = "body", dataType = "EasyBuyProduct"), @ApiImplicitParam(name = "file", value = "商品图片（可选）", required = false, paramType = "formData", dataType = "__file")})
    @ApiResponses({@ApiResponse(code = 200, message = "添加成功"), @ApiResponse(code = 400, message = "文件格式错误（仅支持jpg/png/jpeg）或大小超过10MB"), @ApiResponse(code = 500, message = "添加失败"), @ApiResponse(code = 403, message = "权限不足")})
    @CheckPermission({"0"})
    @PostMapping("/addProduct")
    public ResponseResult addProduct(
            @ModelAttribute EasyBuyProduct easyBuyProduct,
            @RequestParam(name = "file", required = false) MultipartFile file) throws IOException, SftpException {
        LOGGER.info("进入 addProduct 方法，商品信息：{}，是否携带图片：{}", easyBuyProduct, file != null && !file.isEmpty());

        String fileName = null;
        // 处理图片上传（若有）
        if (file != null && !file.isEmpty()) {
            String originalFileName = file.getOriginalFilename();
            String fileExt = originalFileName.substring(originalFileName.lastIndexOf("."));
            // 校验文件格式
            if (!fileExt.equalsIgnoreCase(".jpg") && !fileExt.equalsIgnoreCase(".png") && !fileExt.equalsIgnoreCase(".jpeg")) {
                LOGGER.error("addProduct 文件格式错误：{}", fileExt);
                return ResponseResult.error("400", "文件格式错误，请上传jpg/png/jpeg图片");
            }
            // 校验文件大小
            if (file.getSize() > 1024 * 1024 * 10) {
                LOGGER.error("addProduct 文件大小超限：{}MB", file.getSize() / (1024 * 1024));
                return ResponseResult.error("400", "文件大小不能超过10MB");
            }
            // 生成唯一文件名
            fileName = UUID.randomUUID().toString().replace("-", "").toUpperCase() + fileExt;
            easyBuyProduct.setFileName(fileName);
            LOGGER.info("addProduct 图片处理完成，新文件名：{}", fileName);
        }

        easyBuyProduct.setCreateTime(new Date());
        // 新增商品
        boolean addSuccess = easyBuyProductService.addProduct(easyBuyProduct);
        if (addSuccess) {
            // 上传图片到SFTP（若有）
            if (file != null && !file.isEmpty()) {
                sftpUtil.login();
                sftpUtil.upload("/home/shared/imageServer", fileName, file.getInputStream());
                sftpUtil.logout();
                LOGGER.info("addProduct 图片上传成功：{}", fileName);
            }
            LOGGER.info("addProduct 商品添加成功，ID：{}", easyBuyProduct.getId());
            return ResponseResult.success().add("msg", "添加成功").add("productId", easyBuyProduct.getId());
        } else {
            LOGGER.error("addProduct 商品添加失败：{}", easyBuyProduct);
            throw new BusinessException("添加失败");
        }
    }

    /**
     * 根据ID获取商品详情
     * 管理员和普通用户均可访问，返回商品完整信息
     */
    @ApiOperation(value = "获取商品详情", notes = "根据商品ID查询完整信息；需管理员/普通用户权限", httpMethod = "GET")
    @ApiImplicitParam(name = "id", value = "商品ID", required = true, paramType = "path", dataType = "long", example = "1001")
    @ApiResponses({@ApiResponse(code = 200, message = "查询成功", response = EasyBuyProduct.class), @ApiResponse(code = 404, message = "商品不存在"), @ApiResponse(code = 500, message = "服务器内部错误")})
    @GetMapping("/getProductById/{id}")
    public ResponseResult getProductById(@PathVariable("id") Long id) {
        LOGGER.info("进入 getProductById 方法，商品ID：{}", id);

        // 查询商品详情
        EasyBuyProduct product = easyBuyProductService.getProductById(id);
        if (product == null) {
            LOGGER.warn("getProductById 商品不存在：{}", id);
            return ResponseResult.error("404", "商品不存在");
        }

        LOGGER.info("getProductById 查询成功：{}", product.getId());
        return ResponseResult.success().add("product", product);
    }

    /**
     * 更新商品信息（支持图片更新）
     * 仅超级管理员可操作，上传新图片时自动删除旧图片
     */
    @ApiOperation(value = "更新商品", notes = "仅超级管理员权限；未传新图片则保留原图片；传新图片时自动删除SFTP旧图片", httpMethod = "POST")
    @ApiImplicitParams({@ApiImplicitParam(name = "easyBuyProduct", value = "待更新商品信息（含ID）", required = true, paramType = "body", dataType = "EasyBuyProduct"), @ApiImplicitParam(name = "file", value = "新商品图片（可选）", required = false, paramType = "formData", dataType = "__file")})
    @ApiResponses({@ApiResponse(code = 200, message = "更新成功"), @ApiResponse(code = 400, message = "文件格式/大小错误"), @ApiResponse(code = 404, message = "商品不存在"), @ApiResponse(code = 500, message = "更新失败"), @ApiResponse(code = 403, message = "权限不足")})
    @CheckPermission({"0"})
    @PostMapping("/updateProduct")
    public ResponseResult updateProduct(
            @ModelAttribute EasyBuyProduct easyBuyProduct,
            @RequestParam(name = "file", required = false) MultipartFile file) throws IOException, SftpException {
        Long productId = easyBuyProduct.getId();
        LOGGER.info("进入 updateProduct 方法，商品ID：{}，是否携带新图片：{}", productId, file != null && !file.isEmpty());

        // 校验商品是否存在
        EasyBuyProduct oldProduct = easyBuyProductService.getProductById(productId);
        if (oldProduct == null) {
            LOGGER.error("updateProduct 商品不存在：{}", productId);
            return ResponseResult.error("404", "商品不存在");
        }

        String oldFileName = oldProduct.getFileName();
        String newFileName = null;
        // 处理新图片（若有）
        if (file != null && !file.isEmpty()) {
            String originalFileName = file.getOriginalFilename();
            String fileExt = originalFileName.substring(originalFileName.lastIndexOf("."));
            // 校验文件格式和大小
            if (!fileExt.equalsIgnoreCase(".jpg") && !fileExt.equalsIgnoreCase(".png") && !fileExt.equalsIgnoreCase(".jpeg")) {
                LOGGER.error("updateProduct 文件格式错误：{}", fileExt);
                return ResponseResult.error("400", "文件格式错误，请上传jpg/png/jpeg图片");
            }
            if (file.getSize() > 1024 * 1024 * 10) {
                LOGGER.error("updateProduct 文件大小超限：{}MB", file.getSize() / (1024 * 1024));
                return ResponseResult.error("400", "文件大小不能超过10MB");
            }
            // 生成新文件名
            newFileName = UUID.randomUUID().toString().replace("-", "").toUpperCase() + fileExt;
            easyBuyProduct.setFileName(newFileName);
            LOGGER.info("updateProduct 新图片处理完成：{}", newFileName);
        } else {
            // 未传新图片，保留原文件名
            easyBuyProduct.setFileName(oldFileName);
            LOGGER.info("updateProduct 未传新图片，保留原图片：{}", oldFileName);
        }
        easyBuyProduct.setCreateTime(oldProduct.getCreateTime());
        // 更新商品信息
        boolean updateSuccess = easyBuyProductService.updateProduct(easyBuyProduct);
        if (updateSuccess) {
            // 上传新图片并删除旧图片（若有新图片）
            if (file != null && !file.isEmpty()) {
                sftpUtil.login();
                // 删除旧图片
                if (oldFileName != null) {
                    sftpUtil.delete("/home/shared/imageServer/", oldFileName);
                    LOGGER.info("updateProduct 删除旧图片：{}", oldFileName);
                }
                // 上传新图片
                sftpUtil.upload("/home/shared/imageServer", newFileName, file.getInputStream());
                sftpUtil.logout();
                LOGGER.info("updateProduct 新图片上传成功：{}", newFileName);
            }
            LOGGER.info("updateProduct 商品更新成功：{}", productId);
            return ResponseResult.success().add("msg", "更新成功");
        } else {
            LOGGER.error("updateProduct 商品更新失败：{}", productId);
            throw new BusinessException("更新失败");
        }
    }

    /**
     * 根据ID删除商品
     * 仅超级管理员可操作，同时删除SFTP对应的商品图片
     */
    @ApiOperation(value = "删除商品", notes = "仅超级管理员权限；删除商品时自动删除SFTP上的对应图片", httpMethod = "DELETE")
    @ApiImplicitParam(name = "id", value = "商品ID", required = true, paramType = "path", dataType = "long", example = "1001")
    @ApiResponses({@ApiResponse(code = 200, message = "删除成功"), @ApiResponse(code = 404, message = "商品不存在"), @ApiResponse(code = 500, message = "删除失败"), @ApiResponse(code = 403, message = "权限不足")})
    @CheckPermission({"0"})
    @DeleteMapping("/deleteProductById/{id}")
    public ResponseResult deleteProductById(@PathVariable("id") Long id) throws SftpException {
        LOGGER.info("进入 deleteProductById 方法，商品ID：{}", id);

        // 校验商品是否存在并获取图片名
        EasyBuyProduct product = easyBuyProductService.getProductById(id);
        if (product == null) {
            LOGGER.warn("deleteProductById 商品不存在：{}", id);
            return ResponseResult.error("404", "商品不存在");
        }
        String fileName = product.getFileName();

        // 删除商品
        boolean deleteSuccess = easyBuyProductService.deleteProduct(id);
        if (deleteSuccess) {
            // 删除SFTP图片（若有）
            if (fileName != null) {
                sftpUtil.login();
                sftpUtil.delete("/home/shared/imageServer/", fileName);
                sftpUtil.logout();
                LOGGER.info("deleteProductById 删除图片：{}", fileName);
            }
            LOGGER.info("deleteProductById 商品删除成功：{}", id);
            return ResponseResult.success().add("msg", "删除成功");
        } else {
            LOGGER.error("deleteProductById 商品删除失败：{}", id);
            throw new BusinessException("删除失败");
        }
    }

    /**
     * 首页公开查询商品
     * 无需权限，支持分页和多条件筛选，默认页码1、页大小10
     */
    @ApiOperation(value = "首页查询商品", notes = "公开接口（无需权限）；支持分页+分类/名称筛选；默认页码1、页大小10", httpMethod = "GET")
    @ApiImplicitParams({@ApiImplicitParam(name = "pageNum", value = "当前页码", required = false, paramType = "query", dataType = "int", defaultValue = "1", example = "1"), @ApiImplicitParam(name = "pageSize", value = "每页条数", required = false, paramType = "query", dataType = "int", defaultValue = "10", example = "10"), @ApiImplicitParam(name = "productName", value = "商品名称（模糊匹配）", required = false, paramType = "query", dataType = "string", example = "手机"), @ApiImplicitParam(name = "categoryLevel1Id", value = "一级分类ID", required = false, paramType = "query", dataType = "int", example = "1"), @ApiImplicitParam(name = "categoryLevel2Id", value = "二级分类ID", required = false, paramType = "query", dataType = "int", example = "2"), @ApiImplicitParam(name = "categoryLevel3Id", value = "三级分类ID", required = false, paramType = "query", dataType = "int", example = "3")})
    @ApiResponses({@ApiResponse(code = 200, message = "查询成功", response = PageInfo.class), @ApiResponse(code = 500, message = "服务器内部错误")})
    @GetMapping("/searchProduct")
    public ResponseResult searchProduct(@RequestParam(defaultValue = "1") int pageNum, @RequestParam(defaultValue = "10") int pageSize, @RequestParam(required = false) String productName, @RequestParam(required = false) Integer categoryLevel1Id, @RequestParam(required = false) Integer categoryLevel2Id, @RequestParam(required = false) Integer categoryLevel3Id) {
        LOGGER.info("进入 searchProduct 方法，页码：{}，页大小：{}，商品名称：{}", pageNum, pageSize, productName);

        // 组装查询参数
        Map<String, Object> params = new HashMap<>();
        params.put("pageNum", pageNum);
        params.put("pageSize", pageSize);
        if (categoryLevel1Id != null) params.put("categoryLevel1Id", categoryLevel1Id);
        if (categoryLevel2Id != null) params.put("categoryLevel2Id", categoryLevel2Id);
        if (categoryLevel3Id != null) params.put("categoryLevel3Id", categoryLevel3Id);
        if (productName != null) params.put("productName", productName);

        // 查询商品并返回
        PageInfo<EasyBuyProduct> pageInfo = easyBuyProductService.getAllProduct(params);
        LOGGER.info("searchProduct 查询完成，总记录数：{}", pageInfo.getTotal());
        return ResponseResult.success().add("pageInfo", pageInfo);
    }

    /**
     * 添加商品收藏
     * 管理员和普通用户均可操作，收藏前校验商品是否存在，结果存入Redis
     */
    @ApiOperation(value = "添加商品收藏", notes = "需管理员/普通用户权限；收藏前校验商品是否存在；收藏关系存入Redis", httpMethod = "POST")
    @ApiImplicitParams({@ApiImplicitParam(name = "userId", value = "用户ID", required = true, paramType = "path", dataType = "long", example = "2001"), @ApiImplicitParam(name = "productId", value = "商品ID", required = true, paramType = "path", dataType = "long", example = "1001")})
    @ApiResponses({@ApiResponse(code = 200, message = "收藏成功"), @ApiResponse(code = 400, message = "商品不存在"), @ApiResponse(code = 5001, message = "收藏失败（Redis操作失败）"), @ApiResponse(code = 403, message = "权限不足")})
    @CheckPermission({"0", "1"})
    @PostMapping("/addFavorite/{productId}")
    public ResponseResult addFavorite(@RequestAttribute("userId") Long userId,
                                      @PathVariable("productId") Long productId) {
        LOGGER.info("进入 addFavorite 方法，用户ID：{}，商品ID：{}", userId, productId);

        // 校验商品是否存在
        if (easyBuyProductService.getProductById(productId) == null) {
            LOGGER.warn("addFavorite 商品不存在：用户{}，商品{}", userId, productId);
            return ResponseResult.error("400", "商品不存在");
        }

        // 添加收藏（操作Redis）
        boolean addSuccess = easyBuyProductService.addFavorite(userId, productId);
        if (addSuccess) {
            LOGGER.info("addFavorite 收藏成功：用户{}，商品{}", userId, productId);
            return ResponseResult.success().add("msg", "添加成功");
        } else {
            LOGGER.error("addFavorite Redis操作失败：用户{}，商品{}", userId, productId);
            return ResponseResult.error("5001", "添加失败,redis添加失败");
        }
    }

    /**
     * 获取用户收藏列表
     * 管理员和普通用户均可操作，从Redis获取商品ID，再查询商品详情
     */
    @ApiOperation(value = "获取收藏列表", notes = "需管理员/普通用户权限；从Redis获取收藏ID，再查询商品详情；空列表返回提示", httpMethod = "GET")
    @ApiImplicitParam(name = "userId", value = "用户ID", required = true, paramType = "query", dataType = "long", example = "2001")
    @ApiResponses({@ApiResponse(code = 200, message = "查询成功", response = List.class, responseContainer = "List"), @ApiResponse(code = 200, message = "收藏列表为空"), @ApiResponse(code = 500, message = "服务器内部错误"), @ApiResponse(code = 403, message = "权限不足")})
    @CheckPermission({"0", "1"})
    @GetMapping("/getFavoriteList")
    public ResponseResult getFavoriteList(@RequestAttribute("userId") Long userId) {
        LOGGER.info("进入 getFavoriteList 方法，用户ID：{}", userId);

        // 从Redis获取收藏的商品ID列表
        List<Long> productIdList = easyBuyProductService.getFavoriteList(userId);
        if (productIdList == null || productIdList.isEmpty()) {
            LOGGER.info("getFavoriteList 用户{}收藏列表为空", userId);
            return ResponseResult.success("收藏列表为空");
        }
        LOGGER.info("getFavoriteList 用户{}获取收藏ID数量：{}", userId, productIdList.size());

        // 查询商品详情
        List<EasyBuyProduct> productList = new ArrayList<>();
        for (Long productId : productIdList) {
            EasyBuyProduct product = easyBuyProductService.getProductById(productId);
            if (product != null) {
                productList.add(product);
            } else {
                LOGGER.warn("getFavoriteList 用户{}收藏的商品{}不存在", userId, productId);
            }
        }

        LOGGER.info("getFavoriteList 用户{}收藏商品列表查询完成，数量：{}", userId, productList.size());
        return ResponseResult.success().add("list", productList);
    }

    /**
     * 取消商品收藏
     * 管理员和普通用户均可操作，从Redis删除用户-商品收藏关系
     */
    @ApiOperation(value = "取消商品收藏", notes = "需管理员/普通用户权限；从Redis删除对应的收藏关系", httpMethod = "DELETE")
    @ApiImplicitParams({@ApiImplicitParam(name = "userId", value = "用户ID", required = true, paramType = "path", dataType = "long", example = "2001"), @ApiImplicitParam(name = "productId", value = "商品ID", required = true, paramType = "path", dataType = "long", example = "1001")})
    @ApiResponses({@ApiResponse(code = 200, message = "取消收藏成功"), @ApiResponse(code = 400, message = "取消收藏失败"), @ApiResponse(code = 403, message = "权限不足")})
    @CheckPermission({"0", "1"})
    @DeleteMapping("/deleteFavorite/{productId}")
    public ResponseResult deleteFavorite(@RequestAttribute("userId") Long userId,
                                         @PathVariable("productId") Long productId) {
        LOGGER.info("进入 deleteFavorite 方法，用户ID：{}，商品ID：{}", userId, productId);

        // 取消收藏（删除Redis关系）
        boolean deleteSuccess = easyBuyProductService.deleteFavorite(userId, productId);
        if (deleteSuccess) {
            LOGGER.info("deleteFavorite 取消收藏成功：用户{}，商品{}", userId, productId);
            return ResponseResult.success().add("msg", "删除成功");
        } else {
            LOGGER.error("deleteFavorite 取消收藏失败：用户{}，商品{}", userId, productId);
            return ResponseResult.error("400", "删除失败");
        }
    }

    //检查商品是否被收藏
    @ApiOperation(value = "检查商品是否被收藏", notes = "需管理员/普通用户权限；检查用户是否收藏了指定商品", httpMethod = "GET")
    @ApiImplicitParams({@ApiImplicitParam(name = "userId", value = "用户ID", required = true, paramType = "path", dataType = "long", example = "2001"), @ApiImplicitParam(name = "productId", value = "商品ID", required = true, paramType = "path", dataType = "long", example = "1001")})
    @ApiResponses({@ApiResponse(code = 200, message = "检查成功", response = Boolean.class), @ApiResponse(code = 403, message = "权限不足")})
    @CheckPermission({"0", "1"})
    @GetMapping("/checkFavorite/{productId}")
    public ResponseResult checkFavorite(@RequestAttribute("userId") Long userId,
                                        @PathVariable("productId") Long productId) {
        LOGGER.info("进入 checkFavorite 方法，用户ID：{}，商品ID：{}", userId, productId);

        // 检查收藏（查询Redis关系）
        boolean isFavorite = easyBuyProductService.isProductNotFavorited(userId, productId);
        if (isFavorite) {
            LOGGER.info("checkFavorite 商品{}已被用户{}收藏", productId, userId);
            return ResponseResult.success().add("msg", true);
        } else {
            LOGGER.info("checkFavorite 商品{}未被用户{}收藏", productId, userId);
            return ResponseResult.success().add("msg", false);
        }
    }
}